﻿namespace A2DFramework.OSGI.BundleContexts
{
    using A2DFramework.OSGI.Configuration;
    using A2DFramework.OSGI.Processors;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;

    public class BundleContext : MarshalByRefObject
    {
        private static BundleRuntimeProcessor _processor;

        public string GetDllName(string requestType)
        {
            return GetRuntime().GetDllName(requestType);
        }

        internal ModuleInfo GetModuleInfo(string moduleName)
        {
            return GetRuntime().GetModuleInfo(moduleName);
        }

        public string GetModuleName(string requestType)
        {
            return GetRuntime().GetModuleName(requestType);
        }

        public TI GetProvidedService<TI>()
        {
            return (TI) this.GetProvidedService(typeof(TI).FullName);
        }

        public object GetProvidedService(string requestType)
        {
            return this.GetProvidedServices(requestType).First<object>();
        }

        public List<object> GetProvidedServices(string requestType)
        {
            object obj2;
            List<object> list = new List<object>();
            List<KeyValuePair<string, string>> serviceMap = GetRuntime().GetServiceMap(requestType);
            foreach (KeyValuePair<string, string> pair in serviceMap)
            {
                obj2 = GetRuntime().CreateNewInstance(pair.Key, pair.Value);
                list.Add(obj2);
            }
            RemoteServiceInfo remoteServiceMap = GetRuntime().GetRemoteServiceMap(requestType);
            if (remoteServiceMap != null)
            {
                obj2 = GetRuntime().CreateNewInstance(remoteServiceMap);
                list.Add(obj2);
            }
            return list;
        }

        protected static BundleRuntimeProcessor GetRuntime()
        {
            if (AppDomain.CurrentDomain.IsDefaultAppDomain())
            {
                return BundleRuntimeProcessor.Current;
            }
            if (_processor == null)
            {
                AppDomain data = AppDomain.CurrentDomain.GetData("RuntimeAppDomain") as AppDomain;
                _processor = ((BundleRuntimeProcessor) data.CreateInstanceAndUnwrap("OSGIFramework", typeof(BundleRuntimeProcessor).FullName)).GetGlobalProcessor();
            }
            return _processor;
        }

        internal string GetServiceProviderDllName(string requestType)
        {
            return GetRuntime().GetServiceProviderDllName(requestType);
        }

        public bool IsRegisteredService(string requestType)
        {
            List<KeyValuePair<string, string>> serviceMap = GetRuntime().GetServiceMap(requestType);
            foreach (KeyValuePair<string, string> pair in serviceMap)
            {
                if (pair.Key == this.Name)
                {
                    return true;
                }
            }
            return false;
        }

        internal void RegisterOSGIService(string requestServiceType, int prot, string serviceUri)
        {
            GetRuntime().RegisterOSGIService(requestServiceType, prot, serviceUri);
        }

        public void RegisterProvidedService<TI, TImpl>() where TImpl: class, TI, new()
        {
            string fullName = typeof(TI).FullName;
            string providerType = typeof(TImpl).FullName;
            string name = typeof(TI).Module.Name;
            string providerTypeDllFileName = typeof(TImpl).Module.Name;
            this.RegisterProvidedService(fullName, providerType, name, providerTypeDllFileName);
        }

        public void RegisterProvidedService(string requestType, string providerType, string requestTypeDllFileName, string providerTypeDllFileName)
        {
            GetRuntime().AddServiceMap(this.Name, requestType, providerType, requestTypeDllFileName, providerTypeDllFileName);
        }

        public void UnRegisterProvidedService<TI, TImpl>() where TImpl: class, TI, new()
        {
            string fullName = typeof(TI).FullName;
            string providerType = typeof(TImpl).FullName;
            this.UnRegisterProvidedService(fullName, providerType);
        }

        public void UnRegisterProvidedService(string requestType, string providerType)
        {
            GetRuntime().DeleteServiceMap(this.Name, requestType, providerType);
        }

        public static BundleContext Current
        {
            get
            {
                if (AppDomain.CurrentDomain.IsDefaultAppDomain())
                {
                    return RuntimeContext.Current;
                }
                return SandBoxModuleContext.Current;
            }
        }

        public string Name { get; set; }
    }
}

